package com.core.springSecurity.filter;


import com.common.exception.BusinessException;
import com.common.utils.StringUtils;
import com.core.springSecurity.common.AnonymousHolder;
import com.core.springSecurity.common.AntPathMatcher;
import com.core.springSecurity.common.SecurityUtils;
import com.core.springSecurity.model.LoginUserDetails;
import com.core.springSecurity.service.TokenService;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Resource;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * token过滤器 验证token有效性
 *
 *
 */
@Slf4j
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Resource
    private TokenService tokenService;

    static AntPathMatcher antPathMatcher;

    public static void setAntPathMatcher(AntPathMatcher antPathMatcher) {
        JwtAuthenticationTokenFilter.antPathMatcher = antPathMatcher;
    }

    /**
     * 原先验证方式
     * @param request
     * @param response
     * @param chain
     * @throws ServletException
     * @throws IOException
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        try {
            String servletPath = request.getServletPath();

            LoginUserDetails loginUserDetails = tokenService.getLoginUser(request);
            if (StringUtils.isNotNull(loginUserDetails) && StringUtils.isNull(SecurityUtils.getAuthentication())) {
                tokenService.verifyToken(loginUserDetails);
                UsernamePasswordAuthenticationToken authenticationToken =
                        new UsernamePasswordAuthenticationToken(loginUserDetails, null, loginUserDetails.getAuthorities());
                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                if (!antPathMatcher.matcher(servletPath)) {
                    //**没被过滤的方法应该保存token信息到 SecurityContextHolder，交给后续验证器进行验证*//*
                    log.debug("{},请求路径：{}", loginUserDetails.getUsername(), request.getServletPath());
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                } else {
                    //**被过滤的方法应该保存token信息到 AnonymousHolder，不能保存到SecurityContextHolder，否则验证器报错*//*
                    log.debug("请求路径：{},token:{}", request.getServletPath(), request.getHeader("Authorization"));
                    AnonymousHolder.setLoginUserDetails(loginUserDetails);
                }
            } else {
                //** 没被过滤的方法并且没有带token，应该创建一个游客访问记录 *//*
                if (AnonymousHolder.matcher(servletPath)) {
                    AnonymousHolder.setLoginUserDetails(request);
                }
            }
        } catch (BusinessException e) {
            e.printStackTrace();
            log.error("获取token失败 code:{},msg:{}",e.getErrorCodeEnum().getErrorCode(),e.getErrorCodeEnum().getErrorMsg());
            throw e;
        }catch (Exception e){
            e.printStackTrace();
            log.error("获取token失败 且异常未被捕获");
            throw e;
        }
        chain.doFilter(request, response);
    }

    /**
     * 苗木现在验证方式
     * @param request
     * @param response
     * @param chain
     * @throws ServletException
     * @throws IOException
     */
  /*  @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        try {
            String servletPath = request.getServletPath();

            LoginNurseryUserDetails loginNurseryUserDetails = tokenService.getLoginNurseryUser(request);
            if (StringUtils.isNotNull(loginNurseryUserDetails) && StringUtils.isNull(SecurityUtils.getAuthentication())) {
                tokenService.verifyNurseryToken(loginNurseryUserDetails);
                UsernamePasswordAuthenticationToken authenticationToken =
                        new UsernamePasswordAuthenticationToken(loginNurseryUserDetails, null, loginNurseryUserDetails.getAuthorities());
                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                if (!antPathMatcher.matcher(servletPath)) {
                    *//**没被过滤的方法应该保存token信息到 SecurityContextHolder，交给后续验证器进行验证*//*
                    log.debug("{},请求路径：{}", loginNurseryUserDetails.getUsername(), request.getServletPath());
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                } else {
                    *//**被过滤的方法应该保存token信息到 AnonymousHolder，不能保存到SecurityContextHolder，否则验证器报错*//*
                    log.debug("请求路径：{},token:{}", request.getServletPath(), request.getHeader("Authorization"));
                    AnonymousHolder.setLoginNurseryUserDetails(loginNurseryUserDetails);
                }
            } else {
                *//** 没被过滤的方法并且没有带token，应该创建一个游客访问记录 *//*
                if (AnonymousHolder.matcher(servletPath)) {
                    AnonymousHolder.setLoginUserDetails(request);
                }
            }
        } catch (BusinessException e) {
            e.printStackTrace();
            log.error("获取token失败 code:{},msg:{}",e.getErrorCodeEnum().getErrorCode(),e.getErrorCodeEnum().getErrorMsg());
            throw e;
        }catch (Exception e){
            e.printStackTrace();
            log.error("获取token失败 且异常未被捕获");
            throw e;
        }
        chain.doFilter(request, response);
    }*/
}
